package com.personal.dataanalyse.reportmanage.base;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.personal.core.bean.TwoTuple;
import com.personal.core.data.DataColumn;
import com.personal.core.data.DataColumns;
import com.personal.core.data.DataRow;
import com.personal.core.data.DataRows;
import com.personal.core.data.DataTable;
import com.personal.core.utils.Assert;
import com.personal.core.utils.CoreUtil;
import com.personal.core.utils.DeepChildrenUtil;
import com.personal.dataanalyse.consts.FieldConsts;
import com.personal.dataanalyse.enums.ModelFieldTypeEnum;
import com.personal.dataanalyse.enums.XyTypeEnum;
import com.personal.dataanalyse.reportmanage.builder.ModelFiller;
import com.personal.dataanalyse.reportmanage.builder.impl.DefaultModelFiller;
import com.personal.dataanalyse.reportmanage.entity.DataColumnReportEx;
import com.personal.dataanalyse.reportmanage.entity.DataRowReportEx;
import com.personal.dataanalyse.reportmanage.entity.ReportHeader;
import com.personal.dataanalyse.reportmanage.util.ModelUtil;
import com.personal.dataconvert.DataTable2Html;
import com.personal.dataconvert.bean.CombineColumnConfig;
import com.personal.dataconvert.bean.HeaderConfig;
import com.personal.dataconvert.util.ExcelHtmlUtil;

/**
 * 基础模型
 * @author cuibo
 *
 */
public abstract class DataAnalyseModel implements Serializable, Cloneable
{

    /**
     * 
     * 
     * 
     */
    private static final long serialVersionUID = 6158030091798087891L;
    
    protected static final String REMOVETYPE_HIDE = "HIDE";
    protected static final String REMOVETYPE_NOMATCH = "NOMATCH";
    
    /** 标识 */
    protected String id;

    /** 名称 */
    protected String modelName;

    /**是否需要行列转换*/
    protected boolean transRowCol;

    /** x维度 */
    protected List<DimensionInfo> xGroupFields;

    /** y维度 */
    protected List<DimensionInfo> yGroupFields;

    /** 普通列 */
    protected List<QuotaInfo> columnFields;

    /**计算列 */
    protected List<QuotaInfo> calFields;

    /** 数据源DataTable */
    protected DataTable dataSourceTable;
    
    /** 模型填充 */
    protected ModelFiller<DataAnalyseModel> filler;

    /** 构建的表头信息 */
    protected List<ReportHeader> headerConfigs;
    
    /** 图表模型集合 */
    protected List<DataChartModel> chartModels;
    
    /** X方向是否是不重复的维度，即单行统计数据只在X方向某一列符合要求 */
    protected boolean xNoRepeat = false;
    
    /** Y方向是否是不重复的维度，即单行统计数据只在Y方向某一行符合要求 */
    protected boolean yNoRepeat = false;
    
    /** 只有一个方向存在定义(维度定义和指标定义),且指标为非原值 */
    protected boolean singleGroupModel = false;

    /** 是否是拷贝的标记 */
    protected boolean copyFlag = false;

    /** 表头中的“指标”编辑成需要的字符串 */
    protected String headTargetName;

    /** 表头中的“指标值”编辑成需要的字符串 */
    protected String headTargetValue;
    
    /**
     * 模板方法，通过数据源获取数据
     * @param queryTargetNames
     * @return
     * @throws Exception
     */
    protected abstract DataTable getDataByDataSource(Set<String> queryTargetNames) throws Exception;
    
    @SuppressWarnings("unchecked")
    public void setModelFiller(ModelFiller<? extends DataAnalyseModel> filler)
    {
        this.filler = (ModelFiller<DataAnalyseModel>) filler;
    }

    public List<DataChartModel> getDataChartModels()
    {
        return chartModels;
    }
    
    public void addDataChartModel(DataChartModel model)
    {
        if (chartModels == null)
        {
            chartModels = new ArrayList<DataChartModel>();
        }
        chartModels.add(model);
    }
    
    // toDataTable 供外部调用（做了移除处理）   toDataTableImpl 供子类复用和填充之前调用（没有做移除处理）
    
    /**
     * 转成DataTable
     * @return
     * @throws Exception
     */
    public DataTable toDataTable() throws Exception
    {
        DataTable result = toDataTableImpl();
        handelXSingleGroupTotalModel(result);
        // 移除隐藏行列
        removeRowCol(result, REMOVETYPE_HIDE);
        // 清除计算列，表达式列，附加列的DATA_CLASS样式
        clearIsNotDataClass(result);
        return result;
    }
    
    // toDataTableOnlyStruct 供外部调用（做了移除处理）   toDataTableOnlyStructImpl 供子类复用和填充之前调用（没有做移除处理）
    
    /**
     * 移除不是
     * @param result
     */
    private void clearIsNotDataClass(DataTable result)
    {
        if (!CoreUtil.checkDataTableHasData(result))
        {
            return;
        }
        if (isTransRowCol())
        {
            clearTransRowColIsNotDataClass(result);
        } else
        {
            clearNotTransRowColIsNotDataClass(result);
        }
    }

    private void clearNotTransRowColIsNotDataClass(DataTable result)
    {
        for (DataColumn column : result.getColumns())
        {
            DataColumnReportEx columnEx = (DataColumnReportEx) column;
            if (ModelFieldTypeEnum.isCalField(columnEx.getFieldType()) && CoreUtil.isEmpty(columnEx.getNewDataSql()))
            // if (columnEx.isExpType() || ModelFieldTypeEnum.isCalField(columnEx.getFieldType()))
            {
                for (DataRow row : result.getRows())
                {
                    row.getItemMap().put(column.getColumnName() + DataTable2Html.TDCLASS, FieldConsts.HEAD_CLASS);
                }
            }
        }
        // 附加行
        for (DataRow row : result.getRows())
        {
            DataRowReportEx rowEx = (DataRowReportEx) row;
            if (!rowEx.isAdditionalRow())
            {
                continue;
            }
            for (DataColumn col : result.getColumns())
            {
                rowEx.getItemMap().put(col.getColumnName() + DataTable2Html.TDCLASS, FieldConsts.HEAD_CLASS);
            }
        }
    }

    private void clearTransRowColIsNotDataClass(DataTable result)
    {
        for (DataRow row : result.getRows())
        {
            DataRowReportEx rowEx = (DataRowReportEx) row;
            // 有newdatasql 则允许编辑
            if (ModelFieldTypeEnum.isCalField(rowEx.getFieldType()) && CoreUtil.isEmpty(rowEx.getNewDataSql()))
            // if (rowEx.isExpType() || ModelFieldTypeEnum.isCalField(rowEx.getFieldType()))
            {
                for (DataColumn col : result.getColumns())
                {
                    rowEx.getItemMap().put(col.getColumnName() + DataTable2Html.TDCLASS, FieldConsts.HEAD_CLASS);
                }
            }
        }
        // 附加列
        for (DataColumn column : result.getColumns())
        {
            DataColumnReportEx columnEx = (DataColumnReportEx) column;
            if (!columnEx.isAdditionalCol())
            {
                continue;
            }
            for (DataRow row : result.getRows())
            {
                row.getItemMap().put(column.getColumnName() + DataTable2Html.TDCLASS, FieldConsts.HEAD_CLASS);
            }
        }
    }

    /**
     * 展示报表结构
     * 在toDataTableOnlyStructImpl的基础针对XTotalModel移除了第一个指标值列
     * @return
     * @throws Exception
     */
    public DataTable toDataTableOnlyStruct() throws Exception
    {
        DataTable result = toDataTableOnlyStructImpl();
        handelXSingleGroupTotalModel(result);
        // 移除隐藏行列
        removeRowCol(result, REMOVETYPE_HIDE);
        // 清除计算列，表达式列，附加列的DATA_CLASS样式
        clearIsNotDataClass(result);
        return result;
    }

    /**
     * 转结构实现
     * 子类覆盖
     * @return
     * @throws Exception
     */
    protected DataTable toDataTableOnlyStructImpl() throws Exception
    {
        checkModel();
        DataTable result = new DataTable(this.getModelName());
        // 列信息
        TwoTuple<DataColumns, List<ReportHeader>> columnHeader = creataDataColumnCollection();
        Assert.isNotNullOrEmpty(columnHeader, "构建报表列信息失败！");
        result.getColumns().addAll(columnHeader.getA());
        Assert.isNotNullOrEmpty(result.getColumns(), "构建报表列信息失败！");
        // 设置列号
        int index = 0;
        for (DataColumn dataColumn : result.getColumns())
        {
            DataColumnReportEx columnReportEx = (DataColumnReportEx) dataColumn;
            columnReportEx.setColNum(index++);
        }
        this.headerConfigs = columnHeader.getB();
        // 填充行信息
        DataRows rowCollection = createDataRowCollection(result);
        if (rowCollection != null)
        {
            result.getRows().addAll(rowCollection);
        }
        return result;
    }
    
    /**
     * 转成DataTable实现
     * 子类覆盖
     * @return
     * @throws Exception
     */
    protected DataTable toDataTableImpl() throws Exception
    {
        // 构建报表结构，不能做移除的处理，移除移除之后就不满足行列转换model的行列转换规则
        DataTable result = toDataTableOnlyStructImpl();
        Assert.isNotNull(result, "构建报表结构失败！");
        // 行列转换
        if (isTransRowCol())
        {
            // 将Model中的xGroupFields 和 yGroupFields 互换即可
            DataAnalyseModel tempModel = this.clone();
            List<DimensionInfo> xTemp = this.getxGroupFields();
            tempModel.setxGroupFields(this.getyGroupFields());
            tempModel.setyGroupFields(xTemp);
            // 拷贝之后就不是行列转换
            tempModel.setTransRowCol(false);
            // 是拷贝的Model
            tempModel.setCopyFlag(true);
            // 拷贝之后 X，Y 的NoRepeat需要互换
            tempModel.setxNoRepeat(this.isyNoRepeat());
            tempModel.setyNoRepeat(this.isxNoRepeat());
            // 数据dataTable，只能调用toDataTableImpl方法，因为toDataTable会装饰数据，移除行列
            DataTable dataTable = tempModel.toDataTableImpl();

            // 填充数据行：行列需要转换：转换规则： 
            // struct的行号 + struct的表头行 作为 table的列号
            // struct的列号- struct非数据的列数  作为table的 行号
            int structHeadNum = ModelUtil.getMaxGroupFieldDeep(this.getxGroupFields());
            // 没有X维度只有普通列的时候
            if (structHeadNum == 0)
            {
                structHeadNum = 1;
            }
            // 加1是因为有指标一列
            int structColNum = ModelUtil.getMaxGroupFieldDeep(this.getyGroupFields()) + 1;
            transRowCol(result, dataTable, structHeadNum, structColNum,
                    ModelUtil.getMaxGroupFieldDeep(tempModel.getyGroupFields()));
        } else
        {
            // 填充报表数据
            fillInDataTableData(result);
        }
        return result;
    }
    
    /**
     * 处理X单项该不该移除第一个指标列的问题
     * @param result
     */
    protected void handelXSingleGroupTotalModel(DataTable result)
    {
        // 如果是 XTotalModel需要移除第一个指标值列，
        // 拷贝的Model忽略这个步骤：因为拷贝的需要填充数据
        if (isXSingleGroupTotalModel() && result.getColumns() != null && result.getColumns().size() > 0
                && !this.isCopyFlag())
        {
            result.getColumns().remove(0);
            headerConfigs.remove(0);
        }
    }
    
    // toDataTableOnlyStruct 供外部调用   toDataTableOnlyStructImpl 供子类复用

    /**
     * 手动注入数据源
     * @param table
     * @throws Exception
     */
    public void setDataSourceTable(DataTable table)
    {
        this.dataSourceTable = table;
    }

    /**
     * 填充报表数据
     * @throws Exception 
     */
    protected void fillInDataTableData(DataTable structTable) throws Exception
    {
        ModelFiller<DataAnalyseModel> filler = (this.filler != null ? this.filler : new DefaultModelFiller());
        // 如果手动注入了数据源则直接使用手动注入的数据源
        if (dataSourceTable == null)
        {
            Set<String> queryTargetNames = ModelAnalyzer.loadAllQueryTargetNames(structTable);
            if (queryTargetNames == null || queryTargetNames.isEmpty())
            {
                // 没有数据
                return;
            }
            dataSourceTable = getDataByDataSource(queryTargetNames);
        }
        filler.setModel(this);
        filler.setSourceTable(dataSourceTable);
        filler.setStructTable(structTable);
        // 填充
        filler.fill();
    }

    /**
     * 获取列信息(并创建好表头)
     * @return
     * @throws Exception 
     */
    protected TwoTuple<DataColumns, List<ReportHeader>> creataDataColumnCollection() throws Exception
    {
        return ModelAnalyzer.createDataColumnCollection(this);
    }

    /**
     * 获取行信息
     * @param table
     * @return
     * @throws Exception
     */
    protected DataRows createDataRowCollection(DataTable table) throws Exception
    {
        return ModelAnalyzer.createDataRowCollection(this, table);
    }

    /**
     * 是否是横向汇总Model
     * @return
     */
    public boolean isXSingleGroupTotalModel()
    {
        return isSingleGroupModel() && !isTransRowCol();
    }

    /**
     * 是否是纵向汇总Model
     * @return
     */
    public boolean isYSingleGroupTotalModel()
    {
        return isSingleGroupModel() && isTransRowCol();
    }

    /**
     * 是否是行列转换model的单指标模型
     * @return
     */
    public boolean isYSingleQuoModel()
    {
        if (!isTransRowCol())
        {
            return false;
        }
        int maxDeep = ModelUtil.getTransRowColMaxYGroupFieldDeep(getyGroupFields());
        // 获取最大深度的所有维度
        boolean result = false;
        List<DimensionInfo> dimensionInfos = DeepChildrenUtil.getByDeep(getyGroupFields(), maxDeep);
        if (!CoreUtil.isEmpty(dimensionInfos))
        {
            result = true;
            for (DimensionInfo dimensionInfo : dimensionInfos)
            {
                result = result && dimensionInfo.isSingleQuota();
            }
        }
        return result;
    }
    
    public List<DimensionInfo> getxGroupFields()
    {
        return xGroupFields;
    }

    public void setxGroupFields(List<DimensionInfo> xGroupFields)
    {
        this.xGroupFields = xGroupFields;
    }

    public List<DimensionInfo> getyGroupFields()
    {
        return yGroupFields;
    }

    public void setyGroupFields(List<DimensionInfo> yGroupFields)
    {
        this.yGroupFields = yGroupFields;
    }

    public List<QuotaInfo> getColumnFields()
    {
        return columnFields;
    }

    public void setColumnFields(List<QuotaInfo> columnFields)
    {
        this.columnFields = columnFields;
    }

    public List<QuotaInfo> getCalFields()
    {
        return calFields;
    }

    public void setCalFields(List<QuotaInfo> calFields)
    {
        this.calFields = calFields;
    }

    /**
     * 是否行列翻转
     * 自动判断，根据用户选择的指标列是在XGroupFields中还是在YGroupFields中
     * 方法isXGroupHasField和方法 isTransRowCol互斥
     * @return
     */
    public boolean isTransRowCol()
    {
        return this.transRowCol;
    }

//    public void automaticCheckIsSingleGroupModel()
//    {
//        if (CoreUtil.isEmpty(xGroupFields))
//        {
//            if (CoreUtil.isEmpty(yGroupFields))
//            {
//                singleGroupModel = true;
//                return;
//            }
//            List<AnalyseFactorInfo> factorInfos = new ArrayList<AnalyseFactorInfo>();
//            if (!CoreUtil.isEmpty(columnFields))
//            {
//                factorInfos.addAll(columnFields);
//            }
//            if (!CoreUtil.isEmpty(calFields))
//            {
//                factorInfos.addAll(calFields);
//            }
//            for (AnalyseFactorInfo factor : factorInfos)
//            {
//                if (XyTypeEnum.X == factor.getXy())
//                {
//                    singleGroupModel = false;
//                    return;
//                }
//            }
//            singleGroupModel = true;
//        } else
//        {
//            if (!CoreUtil.isEmpty(yGroupFields))
//            {
//                singleGroupModel = false;
//                return;
//            } 
//            List<AnalyseFactorInfo> factorInfos = new ArrayList<AnalyseFactorInfo>();
//            if (!CoreUtil.isEmpty(columnFields))
//            {
//                factorInfos.addAll(columnFields);
//            }
//            if (!CoreUtil.isEmpty(calFields))
//            {
//                factorInfos.addAll(calFields);
//            }
//            for (AnalyseFactorInfo factor : factorInfos)
//            {
//                if (XyTypeEnum.Y == factor.getXy())
//                {
//                    singleGroupModel = false;
//                    return;
//                }
//            }
//            singleGroupModel = true;
//        }
//    }
    
    /**
     * 只有一个方向存在定义，且指标为非原值
     * @return
     */
    public boolean isSingleGroupModel()
    {
        return singleGroupModel;
    }

    public void setSingleGroupModel(boolean singleGroupModel)
    {
        this.singleGroupModel = singleGroupModel;
    }

    /**
     * X维度是否有指标列
     * 方法isXGroupHasField和方法 isTransRowCol互斥
     * @return
     */
    public boolean isXGroupHasField()
    {
        return !isTransRowCol();
    }

    @Override
    public DataAnalyseModel clone() throws CloneNotSupportedException
    {
        DataAnalyseModel result = (DataAnalyseModel) super.clone();
        if (this.getxGroupFields() != null)
        {
            List<DimensionInfo> xGroupFields = new ArrayList<DimensionInfo>();
            xGroupFields.addAll(this.getxGroupFields());
            result.setxGroupFields(xGroupFields);
        }
        if (this.getyGroupFields() != null)
        {
            List<DimensionInfo> yGroupFields = new ArrayList<DimensionInfo>();
            yGroupFields.addAll(this.getyGroupFields());
            result.setyGroupFields(yGroupFields);
        }
        if (this.getColumnFields() != null)
        {
            List<QuotaInfo> columnFields = new ArrayList<QuotaInfo>();
            columnFields.addAll(this.getColumnFields());
            result.setColumnFields(columnFields);
        }
        if (this.getCalFields() != null)
        {
            List<QuotaInfo> calFields = new ArrayList<QuotaInfo>();
            calFields.addAll(this.getCalFields());
            result.setCalFields(calFields);
        }
        return result;
    }

    /**
     * 行列互换
     * @param struct   结构DataTable
     * @param dataTable  数据DataTable
     * @param structHeadNum  struct的表头行
     * @param structColNum  struct非数据的列数
     * @param colNumAsHead  左边的非数据列数
     */
    private void transRowCol(DataTable struct, DataTable dataTable, int structHeadNum, int structColNum,
            int colNumAsHead)
    {
        if (struct == null || struct.getRows() == null || struct.getColumns() == null)
        {
            return;
        }
        // struct的行号 + struct的表头行 作为 table的列号
        // struct的列号- struct非数据的列数  作为table的 行号

        // table 的列号 - Struct的表头行 = struct的行号
        // table 的行号 + Struct非数据的列数 = struct的列号
        
        // table 的列号  = struct的行号 + Struct的表头行
        // table 的行号  = struct的列号 - Struct非数据的列数 

        // 加载DataTable 数据
        Map<String, Object> allData = loadDataTableData(dataTable, colNumAsHead);
        if (allData == null || allData.isEmpty())
        {
            return;
        }
        fillTransRowCol(struct, dataTable, structHeadNum, structColNum, allData);
        setColumnMatchFlag(struct, dataTable, structColNum);
    }

    private void setColumnMatchFlag(DataTable struct, DataTable dataTable, int structColNum)
    {
        int colIndex = 0;
        for (DataColumn column : struct.getColumns())
        {
            DataColumnReportEx columnEx = (DataColumnReportEx) column;
            int tableRow = colIndex - structColNum;
            if (tableRow >= 0)
            {
                DataRowReportEx rowEx = (DataRowReportEx) dataTable.getRows().get(tableRow);
                columnEx.setMatchData(rowEx.isMatchData());
            } else
            {
                columnEx.setMatchData(true);
            }
            colIndex++;
        }
    }

    private void fillTransRowCol(DataTable struct, DataTable dataTable, int structHeadNum, int structColNum,
            Map<String, Object> allData)
    {
        int rowIndex = 0;
        int colIndex = 0;
        String key = "";
        for (DataRow row : struct.getRows())
        {
            colIndex = 0;
            // 获取行对应的列，并获取匹配标记
            int tableCol = rowIndex + structHeadNum;
            DataColumnReportEx columEx = (DataColumnReportEx) dataTable.getColumns().get(tableCol);
            DataRowReportEx rowEx = (DataRowReportEx) row;
            rowEx.setMatchData(columEx.isMatchData());
            
            for (DataColumn column : struct.getColumns())
            {
                key = (colIndex - structColNum) + "," + (rowIndex + structHeadNum);
                // 行列互换
                if (allData.containsKey(key))
                {
                    row.setValue(column, allData.get(key));
                }
                colIndex++;
            }
            rowIndex++;
        }
    }

    /**
     * 检查模型合法性
     * @throws Exception
     */
    protected void checkModel() throws Exception
    {
        // 判断模型合法性
        if (this.isXGroupHasField())
        {
            if (this.isTransRowCol())
            {
                throw new Exception("X，Y维度不能同时有统计指标！");
            }
        } else
        {
            if (!this.isTransRowCol())
            {
                throw new Exception("模型的统计指标定义为空！");
            }
        }
        // 设置xy维度类别
        ModelUtil.setDimensionXyInfo(this.getxGroupFields(), XyTypeEnum.X);
        ModelUtil.setDimensionXyInfo(this.getyGroupFields(), XyTypeEnum.Y);
        // 将维度和指标的model都设置为新的Model
        ModelUtil.setModel(this);
        // 设置xy维度深度
        ModelUtil.setDimensionInfoDeepLength(this.getxGroupFields());
        ModelUtil.setDimensionInfoDeepLength(this.getyGroupFields());
    }
    
    /**
     * 获取DataTable的所有数据，key：行号,列号  value：值
     * @param table
     * @param colNumAsHead  左边的非数据列数
     * @return
     */
    private Map<String, Object> loadDataTableData(DataTable table, int colNumAsHead)
    {
        Map<String, Object> result = new HashMap<String, Object>();
        int rowIndex = 0;
        int colIndex = 0;
        for (DataRow row : table.getRows())
        {
            colIndex = 0;
            for (DataColumn column : table.getColumns())
            {
                if (colIndex < colNumAsHead)
                {
                    colIndex++;
                    continue;
                }
                result.put(rowIndex + "," + colIndex, row.getItemMap().get(column.getColumnName()));
                colIndex++;
            }
            rowIndex++;
        }
        return result;
    }
    
    /**
     * 创建指标值列
     * @return
     */
    public QuotaInfo createTargetValueQuotaInfo()
    {
        QuotaInfo quotaInfo = new QuotaInfo();
        quotaInfo.setModel(this);
        quotaInfo.createTargetValueQuotaInfo();
        return quotaInfo;
    }
    
    /**
     * 移除行列
     * @param result
     */
    protected void removeRowCol(DataTable result, String removeType)
    {
        if (!CoreUtil.checkDataTableHasColumns(result))
        {
            return;
        }
        removeCol(result, removeType);
        removeRow(result, removeType);
    }

    private void removeRow(DataTable result, String removeType)
    {
        Set<CombineColumnConfig> combineColumnConfigs = ModelUtil.calRegularCombineConfigs(result);
        List<CombineColumnConfigEx> combineColumnConfigExs = null;
        if (!CoreUtil.isEmpty(combineColumnConfigs))
        {
            combineColumnConfigExs = new ArrayList<CombineColumnConfigEx>();
            for (CombineColumnConfig c : combineColumnConfigs)
            {
                combineColumnConfigExs.add(new CombineColumnConfigEx(c, c.getMaxRowScope(), c.getMinRowScope()));
            }
        }
        int rowIndex = -1;
        for (Iterator<DataRow> iterator = result.getRows().iterator(); iterator.hasNext();)
        {
            rowIndex ++;
            DataRowReportEx row = (DataRowReportEx) iterator.next();
            if ((!row.isMatchData() && REMOVETYPE_NOMATCH.equals(removeType)) ||
                    (!row.isDisplay() && REMOVETYPE_HIDE.equals(removeType)))
            {
                iterator.remove();
                if (!CoreUtil.isEmpty(combineColumnConfigs))
                {
                    subtractMinMaxRowScope(rowIndex, combineColumnConfigExs);
                }
            }
        }
    }

    private void removeCol(DataTable result, String removeType)
    {
        for (Iterator<DataColumn> iterator = result.getColumns().iterator(); iterator.hasNext();)
        {
            DataColumnReportEx column = (DataColumnReportEx) iterator.next();
            if ((!column.isMatchData() && REMOVETYPE_NOMATCH.equals(removeType)) || 
                    (!column.isDisplay() && REMOVETYPE_HIDE.equals(removeType)))
            {
                iterator.remove();
                // 移除表头配置
                ExcelHtmlUtil.removeHeaderConfig(headerConfigs, column.getHeaderConfig());
                // 如果当前移除的节点是子节点，并且父节点没有了子节点，则移除父亲节点
                HeaderConfig parent = column.getHeaderConfig();
                while ((parent = parent.getParent()) != null)
                {
                    if (parent.isLeaf())
                    {
                        ExcelHtmlUtil.removeHeaderConfig(headerConfigs, parent);
                    }
                }
            }
        }
    }
    
    /**
     * 当出现行移除时需要重新修改合并配置中的minScope和maxScope的值
     * @param rowIndex
     * @param combineColumnConfigExs
     * @param min
     * @param max
     */
    private void subtractMinMaxRowScope(int rowIndex, List<CombineColumnConfigEx> combineColumnConfigExs)
    {
        for (CombineColumnConfigEx c : combineColumnConfigExs)
        {
            if (rowIndex >= c.getMinRowScope() && rowIndex < c.getMaxRowScope())
            {
                c.getCombineColumnConfig().setMaxRowScope(c.getCombineColumnConfig().getMaxRowScope() - 1);
            } else if (c.getMinRowScope() > rowIndex)
            {
                // 最大最小都减一
                c.getCombineColumnConfig().setMaxRowScope(c.getCombineColumnConfig().getMaxRowScope() - 1);
                c.getCombineColumnConfig().setMinRowScope(c.getCombineColumnConfig().getMinRowScope() - 1);
            }
        }
    }
    
    public String getHeadTargetName()
    {
        return headTargetName;
    }

    public void setHeadTargetName(String headTargetName)
    {
        this.headTargetName = headTargetName;
    }

    public String getId()
    {
        return id;
    }

    public void setId(String id)
    {
        this.id = id;
    }

    public String getModelName()
    {
        return modelName;
    }

    public void setModelName(String modelName)
    {
        this.modelName = modelName;
    }

    public void setTransRowCol(boolean transRowCol)
    {
        this.transRowCol = transRowCol;
    }

    public boolean isCopyFlag()
    {
        return copyFlag;
    }

    public void setCopyFlag(boolean copyFlag)
    {
        this.copyFlag = copyFlag;
    }

    public List<ReportHeader> getHeaderConfigs()
    {
        return headerConfigs;
    }

    public String getHeadTargetValue()
    {
        return headTargetValue;
    }

    public void setHeadTargetValue(String headTargetValue)
    {
        this.headTargetValue = headTargetValue;
    }

    public boolean isxNoRepeat()
    {
        return xNoRepeat;
    }

    public void setxNoRepeat(boolean xNoRepeat)
    {
        this.xNoRepeat = xNoRepeat;
    }

    public boolean isyNoRepeat()
    {
        return yNoRepeat;
    }

    public void setyNoRepeat(boolean yNoRepeat)
    {
        this.yNoRepeat = yNoRepeat;
    }
    
    private static class CombineColumnConfigEx
    {
        private CombineColumnConfig combineColumnConfig;
        /** 最大行范围 */
        private int maxRowScope = Integer.MAX_VALUE;
        /** 最小行范围 */
        private int minRowScope = -1;
        public CombineColumnConfigEx(CombineColumnConfig combineColumnConfig, int maxRowScope, int minRowScope)
        {
            super();
            this.combineColumnConfig = combineColumnConfig;
            this.maxRowScope = maxRowScope;
            this.minRowScope = minRowScope;
        }
        public CombineColumnConfig getCombineColumnConfig()
        {
            return combineColumnConfig;
        }
        public int getMaxRowScope()
        {
            return maxRowScope;
        }
        public int getMinRowScope()
        {
            return minRowScope;
        }
    }

}